package com.hongyun.tms.infra.excel.converter.dict;

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.hongyun.tms.cache.CacheManager;
import com.hongyun.tms.common.annotation.Dict;
import com.hongyun.tms.domain.DictItemDomain;
import com.hongyun.tms.exception.DictNotFoundException;
import com.hongyun.tms.infra.ApplicationContextUtil;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.List;

/**
 * 对字典字段
 * 1.导出时，字典code翻译为labelText
 * 2.导入时，excel的文本翻译为字典code
 *
 * @author peng.li
 * @date 2024-09-12
 */
public class DictConverter implements Converter<String> {
    private final CacheManager cacheManager;

    public DictConverter() {
        this.cacheManager = ApplicationContextUtil.getBean(CacheManager.class);
    }

    @Override
    public Class<?> supportJavaTypeKey() {
        return String.class;
    }

    @Override
    public WriteCellData<String> convertToExcelData(String value, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) {
        // 转换 code 为 text
        // 获取字段信息
        if (excelContentProperty != null) {
            String fieldName = excelContentProperty.getField().getName();
            Class<?> fieldType = excelContentProperty.getField().getDeclaringClass();
            return new WriteCellData<>(convertDictCodeToLabel(fieldName, value, fieldType));
        }
        return new WriteCellData<>(value);
    }

    @Override
    public String convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) {
        // 获取单元格的文本值
        String text = cellData.getStringValue();

        if (excelContentProperty != null) {
            String fieldName = excelContentProperty.getField().getName();
            Class<?> fieldType = excelContentProperty.getField().getDeclaringClass();

            // 尝试转换 text 为 code
            String code = convertDictLabelToCode(fieldName, text, fieldType);

            if (StringUtils.isBlank(code)) {
                // 如果找不到对应的字典 code，抛出异常并包含行号信息
                throw new DictNotFoundException("字典值找不到: " + text);
            }

            return code;
        }

        return text; // 如果没有字段信息，则返回原始文本
    }


    private String convertDictCodeToLabel(String fieldName, String code, Class<?> fieldType) {
        // 查找字段的 Dict 注解
        for (Field field : fieldType.getDeclaredFields()) {
            if (field.getName().equals(fieldName)) {
                Dict dict = field.getAnnotation(Dict.class);
                if (dict != null) {
                    List<DictItemDomain> dictCache = cacheManager.getDictCache();
                    return dictCache.stream()
                            .filter(x -> x.getDictType().equals(dict.code()) && x.getDictValue().equals(code))
                            .findFirst()  // 获取第一个匹配项
                            .map(DictItemDomain::getDictLabel)  // 如果找到，返回标签
                            .orElse("");  // 如果没找到，返回空字符串或其他默认值
                }
            }
        }
        return code; // 如果没有标记 Dict 注解，则返回原始代码
    }

    private String convertDictLabelToCode(String fieldName, String label, Class<?> fieldType) {
        for (Field field : fieldType.getDeclaredFields()) {
            if (field.getName().equals(fieldName)) {
                Dict dict = field.getAnnotation(Dict.class);
                if (dict != null) {
                    List<DictItemDomain> dictCache = cacheManager.getDictCache();
                    return dictCache.stream()
                            .filter(x -> x.getDictType().equals(dict.code()) && x.getDictLabel().equals(label))
                            .findFirst()
                            .map(DictItemDomain::getDictValue)
                            .orElseThrow(() -> new DictNotFoundException(
                                    String.format("字段'%s'的值'%s'非法", fieldName, label)))
//                            .orElse("")
                            ;
                }
            }
        }
        return label;
    }
}
